Obousmerne odkazy na Interfaces a ref counting

Otázka od: Jan Křížek

24. 9. 2002 17:05

Zdravim,

zacinam pouzivat Interface misto abstraktnich trid a mam nasledujici
problem. Casto mam objekty udrzovane ve stromove strukture - tedy rodic
drzi interface IInterfaceList a v nem ma potomky. Obcas ty potomci
potrebuji naopak mit odkaz na rodice a tak jim predavam jeho interface v
konstruktoru a oni si ho ulozi do privatni promenne - problem je, ze se
zapocita reference a takova struktura se mi nikdy neuvolni. Takze mam na
to nasledujici kod:

IParent = interface(IUnknown)
...

IChild = interface(IUnknown)
...

TChild = class(TInterfacedObject, IChild)
private
  FParent: IParent;
...
  constructor Create(AParent: IParent);
end;

constructor TChild.Create;
begin
  inherited Create;
  FParent := AParent;
  if Assigned(FParent) then FParent._Release;
  ...
end;

To funguje, ale lze nejak udelat prirazeni FParent := AParent, tak aby
se nezvysil RefCount (tedy nezavolalo se _Add).

Honza +
D5Prof

Odpovedá: Erik Salaj

24. 9. 2002 21:04

>To funguje, ale lze nejak udelat prirazeni FParent := AParent, tak aby
>se nezvysil RefCount (tedy nezavolalo se _Add).

skus po priradeni zavolat _Release a pocitadlo dekrementovat
(len pozor na to, aby objekt potom nebol uvolneny skor ako treba).
Samozrejme idealnym riesenim by bola automaticka sprava pameti,
t.j. GC, kde sa o to vobec nemusis starat ale to v COM a Delphi
nie je mozne pouzit (az v Delphi.NET).

Erik

Odpovedá: Jan Křížek

25. 9. 2002 9:45

> >To funguje, ale lze nejak udelat prirazeni FParent :=
> AParent, tak aby
> >se nezvysil RefCount (tedy nezavolalo se _Add).
>
> skus po priradeni zavolat _Release a pocitadlo dekrementovat
> (len pozor na to, aby objekt potom nebol uvolneny skor ako treba).
> Samozrejme idealnym riesenim by bola automaticka sprava pameti,
> t.j. GC, kde sa o to vobec nemusis starat ale to v COM a Delphi
> nie je mozne pouzit (az v Delphi.NET).
>
> Erik
>

Tak to taky delam, jak jsem psal. Ptal jsem se, jestli neexistuje
moznost priradit interface do promenne bez implicitniho zavolani _Add.

Vubec nechapu co na tom resi GC? Jak pozna, ze na rodice uz odkazuji
pouze jeho deti a tedy se muze cela struktura zrusit?

Honza +

Odpovedá: eNca

25. 9. 2002 13:49

Snad to dobre chapu:
Pokud plati, ze
- rodic zna pocet svych potomku
- kazdy potomek vzdy obsahuje prave jednu referenci na sveho rodice
Pak bych na to sel z druheho konce - prepsanim metody _Release na
rodicovi. Tam bych dopsal podminku, ze pokud refcount klesne na hodnotu,
ktera se rovna poctu potomku, tak bych vsechny potomky postupne uvolnil.
Po zruseni posledniho potomka by mela automaticky klesnout refcount
rodice na nulu a ten se tak uvolni automaticky sam.
Samozrejme je treba osetrit, ze behem uvolnovani potomku se mi bude
znovu vyvolavat _Release na rodicovi.
Nezkousel jsem to, snad v tom neni zadna logicka chyba.

eNca


Jan Křížek wrote:

>Tak to taky delam, jak jsem psal. Ptal jsem se, jestli neexistuje
>moznost priradit interface do promenne bez implicitniho zavolani _Add.
>
>Vubec nechapu co na tom resi GC? Jak pozna, ze na rodice uz odkazuji
>pouze jeho deti a tedy se muze cela struktura zrusit?
>
>
>

Odpovedá: Malecek Ondrej

25. 9. 2002 9:05

No, jde to, ikdyz to asi nelze doporucit, bo pri neopatrnem pouziti to vnasi
dost chaos:

pointer( FParent) := pointer( AParent);

O  
> -----Puvodni zprava-----
>
> To funguje, ale lze nejak udelat prirazeni FParent := AParent, tak aby
> se nezvysil RefCount (tedy nezavolalo se _Add).
>
> Honza +
> D5Prof


Odpovedá: Erik Salaj

25. 9. 2002 18:48

>Tak to taky delam, jak jsem psal. Ptal jsem se, jestli neexistuje
>moznost priradit interface do promenne bez implicitniho zavolani _Add.

no mohlo by fungovat bez _Add, ked to pretypujes tak, aby to
nebol interface ale smernik

>Vubec nechapu co na tom resi GC? Jak pozna, ze na rodice uz odkazuji
>pouze jeho deti a tedy se muze cela struktura zrusit?

pozrie sa v pameti. ktore sa pouzivaju a ktore nie, povedzme najjednoduchsi
pripad: na heape ani na stacku ani v ziadnom registry nie je adresa objektu
=> objekt sa nepouziva a GC tuto pamet uvolni. Samozrejme v skutocnosti
sa pouzivaju domyselnejsie algoritmy, ktore to lepsie detekuju a su aj
daleko
rychlejsie. GC je podla mna nevyhnutna zalezitost pre OOP, pretoze bez GC
nie je mozne efektivne riesit spravu pamete pre zlozitejsie vezby medzi
objektami. GC riesi aj ine dolezite problemy, na druhej strane nejake
problemy aj prinasa, napr. nevies dopredu, kedy sa objekt uvolni,
uvolnovanie pameti zvykne na nejaky urcity cas "zastavit" cinnost aplikacie
(zalezi od algoritmu). Zaujimave je, ze GC moze byt v mnohych
pripadoch daleko vykonnejsie aj pametovo menej narocnejsie ako
klasicke rucne alokovanie/uvolnovanie pameti heapu.

Erik

Odpovedá: Jan Křížek

26. 9. 2002 7:42

> >Vubec nechapu co na tom resi GC? Jak pozna, ze na rodice uz odkazuji
> >pouze jeho deti a tedy se muze cela struktura zrusit?
>
> pozrie sa v pameti. ktore sa pouzivaju a ktore nie, povedzme
> najjednoduchsi
> pripad: na heape ani na stacku ani v ziadnom registry nie je
> adresa objektu
> => objekt sa nepouziva a GC tuto pamet uvolni. Samozrejme v
> skutocnosti
> sa pouzivaju domyselnejsie algoritmy, ktore to lepsie detekuju a su aj
> daleko rychlejsie.

Nojo ale ten odkaz v pameti je, protoze rodic ma odkaz na syna a syn na
rodice. Jde o to, ze neni odkaz na zadny prvek z cele te struktury z
venku, tedy ma cela struktura zaniknout - jestli tohle maji GC v sobe
zabudovane, tak jsou to opravdu frajeri (a pak se nedivim, ze tolik
zdrzuji  .

Honza +

Odpovedá: Jan Křížek

26. 9. 2002 10:14

> Snad to dobre chapu:
> Pokud plati, ze
> - rodic zna pocet svych potomku
> - kazdy potomek vzdy obsahuje prave jednu referenci na sveho rodice
> Pak bych na to sel z druheho konce - prepsanim metody _Release na
> rodicovi. Tam bych dopsal podminku, ze pokud refcount klesne
> na hodnotu,
> ktera se rovna poctu potomku, tak bych vsechny potomky
> postupne uvolnil.
> Po zruseni posledniho potomka by mela automaticky klesnout refcount
> rodice na nulu a ten se tak uvolni automaticky sam.
> Samozrejme je treba osetrit, ze behem uvolnovani potomku se mi bude
> znovu vyvolavat _Release na rodicovi.
> Nezkousel jsem to, snad v tom neni zadna logicka chyba.
>
> eNca

Diky za napad, asi bude nejlepsi cesta pres pohrani si s implementaci
_Add a _Release. Me slo hlavne o to, abych to mel vyresene jednou a
obecne, protoze vzdy kdyz to udelam znovu, tak zapomenu na _Release v
tom potomkovi a pak se strasne divim, ze se to nechce uvolnit  

Dik Honza +

Odpovedá: Erik Salaj

26. 9. 2002 18:17

>Nojo ale ten odkaz v pameti je, protoze rodic ma odkaz na syna a syn na
>rodice. Jde o to, ze neni odkaz na zadny prvek z cele te struktury z
>venku, tedy ma cela struktura zaniknout - jestli tohle maji GC v sobe
>zabudovane, tak jsou to opravdu frajeri (a pak se nedivim, ze tolik
>zdrzuji  .

jasne, GC funguje (trochu) zlozitejsie, objekty sa oznacuju napr. tak,
ze sa vychadza zo zaciatocneho objektu aplikacie (alebo viacerych
moznych objektov) a zvysne objekty sa uz urcuju deterministicky
(pomocou RTTI informacii je presne zname, ktore polozky objektu
su smerniky na ine objekty a rekurzivne sa tieto objekty oznacuju).

Erik